package com.zjitc.service.imp;

import com.rabbitmq.client.ConnectionFactory;
import com.zjitc.common.Gsonal;
import com.zjitc.common.ServerResponse;
import com.zjitc.common.redis.RedisCache;
import com.zjitc.mapper.CarMapper;
import com.zjitc.mapper.ExpressMapper;
import com.zjitc.mapper.OrderMapper;
import com.zjitc.mapper.ProductMapper;
import com.zjitc.pojo.*;
import com.zjitc.service.OrderService;
import com.zjitc.utils.old.RedisAuto;
import com.zjitc.utils.old.Utils;
import com.zjitc.vo.PageModel;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Create By IntelliJ IDEA
 *
 * @author: myq
 * @create-Time: 2017/11/23  14:49
 */
@SuppressWarnings("ALL")
@Lazy(false)
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper dao;
    @Autowired
    private ProductMapper pdao;
    @Autowired
    private CarMapper cdao;
    @Autowired
    private ExpressMapper edao;
    @Autowired
    private ConnectionFactory factory;
    @Autowired
    private RedisCache redis;
    @Autowired
    private ExpressServiceImpl expressService;

    /**
     * 交换机
     */
    private final String EXCHANGE_NAME = "Exchange_BigWork";
    private final Integer PAGE_SIZE = 15;
    private final String REDIS_PRODUCT = "products";
    private final String INVENTORY = "inventory";
    private final String ORDER = "order";
    private final String ADD = "add";
    private final String DEL = "del";
    private final String UPDATE_PRODUCT = "updateproduct";
    private final String UPDATE_ORDER = "updateorder";
    private final String ALLORDER = "allorder";
    private static Logger log = Logger.getLogger(OrderServiceImpl.class);


    /**
     * 使用数据库操作的代码是 Orders order = dao.findOrderByoid(oid); List<Orderitem> orderitem =
     * dao.findOrderitem(oid); for (Orderitem i : orderitem) { Product product =
     * pdao.findbypid(i.getPid()); i.setProduct(product); i.setSubtotal(product.getShop_price() *
     * i.getCount()); } order.setOrderitems(orderitem);
     */
    @Override
    public Orders findOrderFromRedis(String uid, String oid) {
        checkredis(uid);
        Orders orders = redis.hashgetObject(ORDER + uid.substring(0, 10), oid, Orders.class);
        if (orders == null) {
            try {
                Thread.sleep(1500);
                return redis.hashgetObject(ORDER + uid.substring(0, 10), oid, Orders.class);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return orders;
    }

    @Override
    public ServerResponse deleteorder(String uid, String oid) {
        String key = ORDER + uid.substring(0, 10);
        redis.delHash(key, oid);
        dao.deleteorderitem(oid);
        int i = dao.deleteorder(oid);
        return ServerResponse.createSuccess();
    }

    @Override
    public int deleteAllorder(String uid) {
        List<Orders> orders = redis.hashListGetAll(uid, Orders.class);
        redis.del(uid);
        final int[] i = {0};
        orders.forEach(order -> {
            dao.deleteorderitem(order.getOid());
            edao.delete(order.getOid());
            dao.deleteorder(order.getOid());
            i[0]++;
        });
        return i[0];
    }

    @Override
    public void update(User user, Orders order) throws SQLException {
        redis.hashset(ORDER + user.getUid().substring(0, 10), order.getOid(), Gsonal.tojson(order));
        dao.update(order);
    }

    /**
     * 添加order到队列
     */
    @Override
    public ServerResponse<Orders> addorder(String aid, Float total, User user, List<Caritem> caritems) {
        checkredis(user.getUid());
        boolean b = hasinventory(caritems);
        if (b == false) {
            return ServerResponse.createError("商品库存已发生变化");
        }
        Address address = cdao.findaddress(aid);
        Orders order = createOrder(user, address, total);
        List<Orderitem> orderitem = createOrderitem(caritems, order.getOid());
        boolean b1 = InsertOrderAndItem(order, orderitem);
        List<Orderitem> orderitemAll = InitOrderitem(orderitem);
        order.setOrderitems(orderitemAll);
        redis.hashset(ORDER + user.getUid().substring(0, 10), order.getOid(), Gsonal.tojson(order));
        return ServerResponse.createSuccess(order.getOid());
    }

    /**
     * 放到缓存的订单详情   预先减缓存 但不处理数据库
     *
     * @param orderitem
     * @return
     */
    private List<Orderitem> InitOrderitem(List<Orderitem> orderitem) {
        orderitem.forEach(item -> {
            Product product = pdao.findbypid(item.getPid());
            redis.hincrby(INVENTORY, item.getPid(), -1 * item.getCount());
            product.setStock(null);
            product.setGrade(null);
            product.setMonthlySales(null);
            product.setShelfTime(null);
            item.setProduct(product);
        });
        return orderitem;
    }

    private boolean InsertOrderAndItem(Orders order, List<Orderitem> orderitem) {
        dao.addorder(order);
        return dao.addorderitem(orderitem) > 0 ? true : false;
    }

    private Orders createOrder(User user, Address address, Float total) {
        Orders orders = new Orders();
        orders.setOid(Utils.getUUID());
        orders.setTotalPrice(total);
        orders.setPhone(address.getTelephone());
        orders.setName(address.getName());
        orders.setAddress(address.getCity() + " " + address.getStreet());
        orders.setCreateTime(Utils.Dateformat(new Date()));
        orders.setState("0");
        orders.setUid(user.getUid());
        return orders;
    }

    private List<Orderitem> createOrderitem(List<Caritem> caritems, String oid) {
        List<Orderitem> orderItems = new ArrayList<>();
        caritems.forEach(caritem -> {
            Orderitem item = new Orderitem();
            item.setOiid(Utils.getUUID());
            item.setCount(caritem.getCount());
            item.setSubtotal(caritem.getPrice());
            item.setPid(caritem.getProduct().getPid());
            item.setOid(oid);
            orderItems.add(item);
        });
        return orderItems;
    }


    @Override
    public List<Orders> findAllOrder() {
        checkredisAll();
        List<Orders> ordersList = redis.hashListGetAll(ALLORDER, Orders.class);
        ordersList.forEach(orders -> {
            if(orders.getState() == "3" || orders.getState() == "4"){
                ordersList.remove(orders);
            }
        });
        return ordersList;
    }

    @Override
    public List<Orders> findHistoryOrder() {
        checkredisAll();
        return redis.hashListGetAll(ALLORDER, Orders.class);
    }

    /**
     * 发货
     */
    @Override
    public boolean shipments( String oid) {
        Orders orders = findOrderbyoid(oid);
        orders.setState("2");
        try {
            Express check = expressService.check(oid);
            if (check == null) {
                expressService.add(oid);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        redis.hashset(ORDER + orders.getUid().substring(0, 10), orders.getOid(), Gsonal.tojson(orders));
        return dao.update(orders) == 1;
    }

    private Orders findOrderbyoid(String oid) {
        Orders orders = dao.findOrderByoid(oid);
        List<Orderitem> orderitems = dao.findOrderitem(oid);
        orderitems.forEach(orderitem -> {
            Product product = pdao.findbypid(orderitem.getPid());
            orderitem.setProduct(product);
        });
        orders.setOrderitems(orderitems);
        return orders;
    }

    @Override
    public void expcheck(String oid) {

    }

    /**
     * 收货
     */
    @Override
    public void confirm(User user, String oid) {
        Orders orders = redis.hashgetObject(ORDER + user.getUid().substring(0,10), oid, Orders.class);
        orders.setState("3");
        redis.hashset(ORDER + user.getUid().substring(0,10), oid, Gsonal.tojson(orders));
        dao.update(orders);
    }

    @Override
    public boolean hasinventory(String pid, String count) {
        Integer stock = redis.hashgetObject(INVENTORY, pid, Integer.class);
        if (stock - Integer.parseInt(count) >= 0) {
            return true;
        }
        return false;
    }

    /**
     * 付款和退款之后的更新库存   未付款不进入
     *
     * @param orderitems
     * @param type
     */
    @Override
    public void updateinventory(List<Orderitem> orderitems, String type) {
        if ("pay".equals(type)) {
            declineInventory(orderitems);
        } else {
            addInventory(orderitems);
        }
    }

    @Override
    public boolean checkOrder(String oid, String uid) {
        Orders orders = findOrderFromRedis(uid, oid);
        return orders.getState() == "0";
    }

    @Override
    public boolean admindeleteOrder(String oid, String uid) {
        redis.delHash(ORDER + uid.substring(0,10), oid);
        dao.deleteorderitem(oid);
        int i = dao.deleteorder(oid);
        return i==1;
    }

    private void addInventory(List<Orderitem> orderitems) {
        orderitems.forEach(item -> {
            Product product = pdao.findbypid(item.getPid());
            product.setStock(product.getStock() + item.getCount());
            pdao.update(product);
        });
    }

    private void declineInventory(List<Orderitem> orderitems) {
        orderitems.forEach(item -> {
            Product product = pdao.findbypid(item.getPid());
            product.setStock(product.getStock() - item.getCount());
            pdao.update(product);
        });
    }

    @Override
    public PageModel<Orders> findPageByUid(String uid, int pageid) {
        checkredis(uid);
        checkinventory();
        List<Orders> ordersList = redis.hashListGetAll(ORDER + uid.substring(0, 10), Orders.class);
        PageModel pageModel = new PageModel(ordersList, PAGE_SIZE, pageid);
        return pageModel;
    }

    private void checkinventory() {
        if (!redis.exists(INVENTORY)) {
            RedisAuto.inventoryRedis(pdao, redis, INVENTORY);
        }
    }

    private void checkredis(String uid) {
        String name = "order" + uid.substring(0, 10);
        if (!redis.exists(name)) {
            RedisAuto.orderRedis(dao, pdao, redis, uid);
        }
    }

    private void checkredisAll() {
        RedisAuto.orderRedisAll(dao, pdao, redis, ALLORDER);
    }

    private boolean hasinventory(List<Caritem> caritems) {
        int flag = 0;
        for (Caritem caritem : caritems) {
            Integer stock = redis
                    .hashgetObject(INVENTORY, caritem.getProduct().getPid(), Integer.class);
            if (stock - caritem.getCount() <= 0) {
                return false;
            }
        }
        return true;
    }
}
